"""
========================================================================
FILE: element_types.py

LAST MODIFIED: 26 August 2009

DESCRIPTION: 
Different types of elements and a constructor function to return
specified types of elements
========================================================================
"""
"""
BEGIN LICENSE BLOCK 
Version: MPL 1.1/GPL 2.0/LGPL 2.1

The contents of this file are subject to the Mozilla Public License Version
1.1 (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/

Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
for the specific language governing rights and limitations under the
License.

The Original Code is fieldwork.

The Initial Developer of the Original Code is Ju Zhang.
Portions created by the Initial Developer are Copyright (C) 2009
the Initial Developer. All Rights Reserved.

Contributor(s):

Alternatively, the contents of this file may be used under the terms of
either the GNU General Public License Version 2 or later (the "GPL"), or
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
in which case the provisions of the GPL or the LGPL are applicable instead
of those above. If you wish to allow use of your version of this file only
under the terms of either the GPL or the LGPL, and not to allow others to
use your version of this file under the terms of the MPL, indicate your
decision by deleting the provisions above and replace them with the notice
and other provisions required by the GPL or the LGPL. If you do not delete
the provisions above, a recipient may use your version of this file under
the terms of any one of the MPL, the GPL or the LGPL.

END LICENSE BLOCK
"""

#!/usr/bin/env python

#======================================================================#
# element classes
# dimension: dimension of the element
# interior: tuple of tuples of the range of value define in the interior 
#			of the elements for each dimension

class Element:
	""" Universal element class
	dimension: dimension of the element
	interior: tuple of tuples of the range of value define in the interior 
			  of the elements for each dimension
			  
	number_of_points: need to be removed. This should be inferred from
	the field basis?
	"""
	
	def __init__( self, dimensions, interior, number_of_points, type ):
		self.dimensions = dimensions							# int
		self.interior = interior								# ( (xi1.min, xi1.max), (xi2.min, xi2.max), ...)
		self.type = type										# string
		self.number_of_points = number_of_points				# int
		self.is_element = True
		return

	def get_number_of_ensemble_points( self ):
		return self.number_of_points


class quad( Element ):
	""" quadralateral elements
	"""
	
	def is_interior( self, coords ):
		
		if len( coords ) != self.dimensions:
			print 'ERROR: quad.is_interior: wrong number of input coordinates. Need', self.dimensions, ', got', len( coords )
			return 0
		
		for i in range( self.dimensions ):
			if not (( coords[i] > self.interior[i][0] ) and ( coords[i] < self.interior[i][1] )):
				return 0
		
		return 1	


class tri( Element ):
	""" simplex elements
	"""
	
	def is_interior( self, coords ):
		
		if len( coords ) != self.dimensions:
			print 'ERROR: quad.is_interior: wrong number of input coordinates. Need', self.dimensions, ', got', len( coords )
			return 0
		else:
			return sum( coords ) <= 1.0
			
	def is_boundary( self, coords ):	
	
		if len( coords ) != self.dimensions:
			print 'ERROR: quad.is_interior: wrong number of input coordinates. Need', self.dimensions, ', got', len( coords )
			return 0
		else:
			return sum( coords ) == 1.0
			
			
#======================================================================#
def create_element( type ):
	""" Contructor function to return an element of the required type 
	with the appropriate number and type of points.	
	"""
	
	element_types = ( 'line2l', 'line2h', 'line3', \
	                  'tri3l', 'tri3h', 'tri6',\
	                  'quad22l', 'quad22h', 'quad23l', 'quad23h',\
					  'quad32l', 'quad32h', 'quad33' )
	
	if type == element_types[0]:
		# linear line
		element = quad( 1, ((0,1)), 2, element_types[0])
		element.add_points( 2, 1 )
	elif type == element_types[1]:
		# cubic hermite line
		element = quad( 1, ((0,1)), 2, element_types[1])
		element.add_points( 2, 2 )
	elif type == element_types[2]:
		# quadratic line
		element = quad( 1, ((0,1)), 3, element_types[2])
		element.add_points( 3, 1 )
	elif type == element_types[3]:
		# linear triangle
		element = tri( 2, ((0,1),(0,1)), 3, element_types[3] )
	elif type == element_types[4]:
		# cubic hermite triangle
		print 'Not implemented'
	elif type == element_types[5]:
		# quadratic triangle
		element = tri( 2, ((0,1),(0,1)), 6, element_types[5] )
	elif type == element_types[6]:
		# linear quad
		element = quad( 2, ((0,1),(0,1)), 4, element_types[6])
	elif type == element_types[7]:
		# cubic hermite quad
		element = quad( 2, ((0,1),(0,1)), 4, element_types[6])
	elif type == element_types[8]:
		# linear quadratic quad
		print 'Not implemented'
	elif type == element_types[9]:
		# cubic hermite quadratic quad
		print 'Not implemented'
	elif type == element_types[10]:
		# quadratic linear quad
		print 'Not implemented'
	elif type == element_types[11]:
		# quadratic cubic hermite quad
		print 'Not implemented'
	elif type == element_types[12]:
		# quadratic quad
		element = quad( 2, ((0,1),(0,1)), 9, element_types[6])
	else:
		print "ERROR: unrecognised element type"
		return None
		
	return element
	
#======================================================================#
